/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nio;

import java.awt.EventQueue;
import java.awt.Toolkit;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.SwingWorker;

/**

 @author Tomek
 */
public class FileDownloadClient extends javax.swing.JFrame implements PropertyChangeListener {

	private static final int port = 9999;
	Socket socket;
	Scanner scanner;
	InputStream inputStream;
	BufferedOutputStream sender;
	SocketChannel channel;
	private DefaultListModel listModel = new DefaultListModel();

	public FileDownloadClient() {
		try {
			initComponents();
			channel = SocketChannel.open(new InetSocketAddress("localhost", port));
			socket = channel.socket();
			inputStream = socket.getInputStream();
			scanner = new Scanner(inputStream);
			sender = new BufferedOutputStream(socket.getOutputStream());
			fileList.setModel(listModel);
		} catch (UnknownHostException ex) {
			Logger.getLogger(FileDownloadClient.class.getName()).log(Level.SEVERE, null, ex);
		} catch (IOException ex) {
			Logger.getLogger(FileDownloadClient.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

	public void send(String message) {
		try {
			sender.write((message + "\n").getBytes());
			sender.flush();
		} catch (IOException ex) {
			Logger.getLogger(FileDownloadClient.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

	/**
	 This method is called from within the constructor to initialize the form.
	 WARNING: Do NOT modify this code. The content of this method is always
	 regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        fileList = new javax.swing.JList();
        getButton = new javax.swing.JButton();
        refreshButton = new javax.swing.JButton();
        progressBar = new javax.swing.JProgressBar();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        fileList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        fileList.setPreferredSize(new java.awt.Dimension(50, 100));
        jScrollPane1.setViewportView(fileList);

        getButton.setText("Pobierz");
        getButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                getButtonActionPerformed(evt);
            }
        });

        refreshButton.setText("Odświerz");
        refreshButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refreshButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(progressBar, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 214, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(refreshButton)
                        .addContainerGap(35, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(getButton, javax.swing.GroupLayout.PREFERRED_SIZE, 77, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(0, 0, Short.MAX_VALUE))))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(26, 26, 26)
                        .addComponent(getButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(refreshButton))
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 240, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void getButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_getButtonActionPerformed
		String value = (String) fileList.getSelectedValue();
		if (value == null) {
			return;
		}
		getButton.setEnabled(false);
		progressBar.setMinimum(0);
		progressBar.setStringPainted(true);
		Task task = new Task(value);
		task.addPropertyChangeListener(this);
		task.execute();

	}//GEN-LAST:event_getButtonActionPerformed
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if (SwingWorker.StateValue.STARTED == evt.getNewValue()) {
			progressBar.setEnabled(true);
			return;
		}
		if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
			EventQueue.invokeLater(new Runnable() {

				public void run() {
					progressBar.setValue(0);
					getButton.setEnabled(true);
				}
			});
			return;
		}
		if ("progress".equals(evt.getPropertyName())) {
			int progress = (Integer) evt.getNewValue();
			progressBar.setValue(progress);
		}
	}
	private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
		send("list");
		EventQueue.invokeLater(new Thread() {

			@Override
			public void run() {
				listModel.clear();
			}
		});
		String line = scanner.nextLine();
		while (line != null && !"".equals(line)) {
			final String lineToAdd = line;
			EventQueue.invokeLater(new Thread() {

				@Override
				public void run() {
					listModel.addElement(lineToAdd);
				}
			});
			line = scanner.nextLine();
		}
	}//GEN-LAST:event_refreshButtonActionPerformed

	/**
	 @param args the command line arguments
	 */
	public static void main(String args[]) {
//		/*
//		 Set the Nimbus look and feel
//		 */
//		//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
//        /*
//		 If Nimbus (introduced in Java SE 6) is not available, stay with the default
//		 look and feel. For details see
//		 http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
//		 */
//		try {
//			for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
//				if ("Nimbus".equals(info.getName())) {
//					javax.swing.UIManager.setLookAndFeel(info.getClassName());
//					break;
//				}
//			}
//		} catch (ClassNotFoundException ex) {
//			java.util.logging.Logger.getLogger(FileDownloadClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//		} catch (InstantiationException ex) {
//			java.util.logging.Logger.getLogger(FileDownloadClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//		} catch (IllegalAccessException ex) {
//			java.util.logging.Logger.getLogger(FileDownloadClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//		} catch (javax.swing.UnsupportedLookAndFeelException ex) {
//			java.util.logging.Logger.getLogger(FileDownloadClient.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
//		}
//		//</editor-fold>

		/*
		 Create and display the form
		 */
		java.awt.EventQueue.invokeLater(new Runnable() {

			public void run() {
				new FileDownloadClient().setVisible(true);
			}
		});
	}
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JList fileList;
    private javax.swing.JButton getButton;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JButton refreshButton;
    // End of variables declaration//GEN-END:variables

	class Task extends SwingWorker<Void, Void> {

		String value;

		public Task(String value) {
			this.value = value;
		}

		@Override
		public Void doInBackground() {
			//Initialize progress property
			setProgress(0);
			send("get " + value);
			int bytes = Integer.parseInt(scanner.nextLine());
			progressBar.setMaximum(bytes);
			int len = bytes;
			ByteBuffer buffer = ByteBuffer.allocate(128);
			try {
				FileOutputStream fos = new FileOutputStream("copy"+value);
				while (bytes > 0) {
					int count = inputStream.read(buffer.array(), 0, bytes > 128 ? 128 : bytes);
					bytes -= count;
					int newProgress = (int)((len - (float)bytes)/ len * 100);
					this.firePropertyChange(SwingWorker.StateValue.PENDING+"", getProgress(), newProgress);
					setProgress(newProgress);
					fos.write(buffer.array(), 0, count);
				}
				fos.close();
				//inputStream.skip(inputStream.available());
			} catch (Exception ex) {
				Logger.getLogger(FileDownloadClient.class.getName()).log(Level.SEVERE, null, ex);
			} finally {
			}
			return null;
		}

		/*
		 Executed in event dispatching thread
		 */
		@Override
		public void done() {
			Toolkit.getDefaultToolkit().beep();
			System.out.println("Done!");
		}
	}
}
